2 * MultiDatesPicker v1.6.1
3 * http://multidatespickr.sourceforge.net/
5 * Copyright 2011, Luca Lauretta
6 * Dual licensed under the MIT or GPL version 2 licenses.
9 $.extend($.ui
, { multiDatesPicker
: { version
: "1.6.1" } });
11 $.fn
.multiDatesPicker = function(method
) {
12 var mdp_arguments
= arguments
;
14 var today_date
= new Date();
15 var day_zero
= new Date(0);
18 function removeDate(date
, type
) {
19 if(!type
) type
= 'picked';
20 date
= dateConvert
.call(this, date
);
21 for(var i
in this.multiDatesPicker
.dates
[type
])
22 if(!methods
.compareDates(this.multiDatesPicker
.dates
[type
][i
], date
))
23 return this.multiDatesPicker
.dates
[type
].splice(i
, 1).pop();
25 function removeIndex(index
, type
) {
26 if(!type
) type
= 'picked';
27 return this.multiDatesPicker
.dates
[type
].splice(index
, 1).pop();
29 function addDate(date
, type
, no_sort
) {
30 if(!type
) type
= 'picked';
31 date
= dateConvert
.call(this, date
);
33 // @todo: use jQuery UI datepicker method instead
37 date
.setMilliseconds(0);
39 if (methods
.gotDate
.call(this, date
, type
) === false) {
40 this.multiDatesPicker
.dates
[type
].push(date
);
41 if(!no_sort
) this.multiDatesPicker
.dates
[type
].sort(methods
.compareDates
);
44 function sortDates(type
) {
45 if(!type
) type
= 'picked';
46 this.multiDatesPicker
.dates
[type
].sort(methods
.compareDates
);
48 function dateConvert(date
, desired_type
, date_format
) {
49 if(!desired_type
) desired_type
= 'object';/*
50 if(!date_format && (typeof date == 'string')) {
51 date_format = $(this).datepicker('option', 'dateFormat');
52 if(!date_format) date_format = $.datepicker._defaults.dateFormat;
55 return methods
.dateConvert
.call(this, date
, desired_type
, date_format
);
59 init : function( options
) {
61 this.multiDatesPicker
.changed
= false;
64 beforeShow: function(input
, inst
) {
65 this.multiDatesPicker
.changed
= false;
66 if(this.multiDatesPicker
.originalBeforeShow
)
67 this.multiDatesPicker
.originalBeforeShow
.call(this, input
, inst
);
69 onSelect : function(dateText
, inst
) {
71 this.multiDatesPicker
.changed
= true;
74 $this.multiDatesPicker('toggleDate', dateText
);
77 if (this.multiDatesPicker
.mode
== 'normal' && this.multiDatesPicker
.dates
.picked
.length
> 0 && this.multiDatesPicker
.pickableRange
) {
78 var min_date
= this.multiDatesPicker
.dates
.picked
[0],
79 max_date
= new Date(min_date
.getTime());
81 methods
.sumDays(max_date
, this.multiDatesPicker
.pickableRange
-1);
83 // counts the number of disabled dates in the range
84 if(this.multiDatesPicker
.adjustRangeToDisabled
) {
86 disabled
= this.multiDatesPicker
.dates
.disabled
.slice(0);
89 for(var i
= 0; i
< disabled
.length
; i
++) {
90 if(disabled
[i
].getTime() <= max_date
.getTime()) {
91 if((min_date
.getTime() <= disabled
[i
].getTime()) && (disabled
[i
].getTime() <= max_date
.getTime()) ) {
94 disabled
.splice(i
, 1);
98 max_date
.setDate(max_date
.getDate() + c_disabled
);
99 } while(c_disabled
!= 0);
102 if(this.multiDatesPicker
.maxDate
&& (max_date
> this.multiDatesPicker
.maxDate
))
103 max_date
= this.multiDatesPicker
.maxDate
;
106 .datepicker("option", "minDate", min_date
)
107 .datepicker("option", "maxDate", max_date
);
110 .datepicker("option", "minDate", this.multiDatesPicker
.minDate
)
111 .datepicker("option", "maxDate", this.multiDatesPicker
.maxDate
);
114 if(this.tagName
== 'INPUT') { // for inputs
116 $this.multiDatesPicker('getDates', 'string')
120 if(this.multiDatesPicker
.originalOnSelect
&& dateText
)
121 this.multiDatesPicker
.originalOnSelect
.call(this, dateText
, inst
);
123 // thanks to bibendus83 -> http://sourceforge.net/tracker/?func=detail&atid=1495384&aid=3403159&group_id=358205
124 if ($this.datepicker('option', 'altField') != undefined && $this.datepicker('option', 'altField') != "") {
125 $($this.datepicker('option', 'altField')).val(
126 $this.multiDatesPicker('getDates', 'string')
130 beforeShowDay : function(date
) {
132 gotThisDate
= $this.multiDatesPicker('gotDate', date
) !== false,
133 isDisabledCalendar
= $this.datepicker('option', 'disabled'),
134 isDisabledDate
= $this.multiDatesPicker('gotDate', date
, 'disabled') !== false,
135 areAllSelected
= this.multiDatesPicker
.maxPicks
== this.multiDatesPicker
.dates
.picked
.length
;
137 var custom
= [true, ''];
138 if(this.multiDatesPicker
.originalBeforeShowDay
)
139 custom
= this.multiDatesPicker
.originalBeforeShowDay
.call(this, date
);
141 var highlight_class
= (gotThisDate
? 'ui-state-highlight' : '') + ((custom
[1] && gotThisDate
) ? ' ' : '') + custom
[1];
142 var selectable_date
= !(isDisabledCalendar
|| isDisabledDate
|| (areAllSelected
&& !highlight_class
));
143 custom
[0] = selectable_date
&& custom
[0];
144 custom
[1] = highlight_class
;
147 onClose: function(dateText
, inst
) {
148 if(this.tagName
== 'INPUT' && this.multiDatesPicker
.changed
) {
149 $(inst
.dpDiv
[0]).stop(false,true);
150 setTimeout('$("#'+inst
.id
+'").datepicker("show")',50);
152 if(this.multiDatesPicker
.originalOnClose
) this.multiDatesPicker
.originalOnClose
.call(this, dateText
, inst
);
157 this.multiDatesPicker
.originalBeforeShow
= options
.beforeShow
;
158 this.multiDatesPicker
.originalOnSelect
= options
.onSelect
;
159 this.multiDatesPicker
.originalBeforeShowDay
= options
.beforeShowDay
;
160 this.multiDatesPicker
.originalOnClose
= options
.onClose
;
162 $this.datepicker(options
);
164 this.multiDatesPicker
.minDate
= $.datepicker
._determineDate(this, options
.minDate
, null);
165 this.multiDatesPicker
.maxDate
= $.datepicker
._determineDate(this, options
.maxDate
, null);
167 if(options
.addDates
) methods
.addDates
.call(this, options
.addDates
);
168 if(options
.addDisabledDates
)
169 methods
.addDates
.call(this, options
.addDisabledDates
, 'disabled');
171 methods
.setMode
.call(this, options
);
176 $this.datepicker('option', mdp_events
);
178 if(this.tagName
== 'INPUT') $this.val($this.multiDatesPicker('getDates', 'string'));
180 // Fixes the altField filled with defaultDate by default
181 var altFieldOption
= $this.datepicker('option', 'altField');
182 if (altFieldOption
) $(altFieldOption
).val($this.multiDatesPicker('getDates', 'string'));
184 compareDates : function(date1
, date2
) {
185 date1
= dateConvert
.call(this, date1
);
186 date2
= dateConvert
.call(this, date2
);
187 // return > 0 means date1 is later than date2
188 // return == 0 means date1 is the same day as date2
189 // return < 0 means date1 is earlier than date2
190 var diff
= date1
.getFullYear() - date2
.getFullYear();
192 diff
= date1
.getMonth() - date2
.getMonth();
194 diff
= date1
.getDate() - date2
.getDate();
198 sumDays : function( date
, n_days
) {
199 var origDateType
= typeof date
;
200 obj_date
= dateConvert
.call(this, date
);
201 obj_date
.setDate(obj_date
.getDate() + n_days
);
202 return dateConvert
.call(this, obj_date
, origDateType
);
204 dateConvert : function( date
, desired_format
, dateFormat
) {
205 var from_format
= typeof date
;
207 if(from_format
== desired_format
) {
208 if(from_format
== 'object') {
212 $.error('Received date is in a non supported format!');
220 if(typeof date
== 'undefined') date
= new Date(0);
222 if(desired_format
!= 'string' && desired_format
!= 'object' && desired_format
!= 'number')
223 $.error('Date format "'+ desired_format
+'" not supported!');
226 dateFormat
= $.datepicker
._defaults
.dateFormat
;
228 // thanks to bibendus83 -> http://sourceforge.net/tracker/index.php?func=detail&aid=3213174&group_id=358205&atid=1495382
229 var dp_dateFormat
= $this.datepicker('option', 'dateFormat');
231 dateFormat
= dp_dateFormat
;
235 // converts to object as a neutral format
236 switch(from_format
) {
237 case 'object': break;
238 case 'string': date
= $.datepicker
.parseDate(dateFormat
, date
); break;
239 case 'number': date
= new Date(date
); break;
240 default: $.error('Conversion from "'+ desired_format
+'" format not allowed on jQuery.multiDatesPicker');
242 // then converts to the desired format
243 switch(desired_format
) {
244 case 'object': return date
;
245 case 'string': return $.datepicker
.formatDate(dateFormat
, date
);
246 case 'number': return date
.getTime();
247 default: $.error('Conversion to "'+ desired_format
+'" format not allowed on jQuery.multiDatesPicker');
251 gotDate : function( date
, type
) {
252 if(!type
) type
= 'picked';
253 for(var i
= 0; i
< this.multiDatesPicker
.dates
[type
].length
; i
++) {
254 if(methods
.compareDates
.call(this, this.multiDatesPicker
.dates
[type
][i
], date
) === 0) {
260 getDates : function( format
, type
) {
261 if(!format
) format
= 'string';
262 if(!type
) type
= 'picked';
265 return this.multiDatesPicker
.dates
[type
];
268 var o_dates
= new Array();
269 for(var i
in this.multiDatesPicker
.dates
[type
])
273 this.multiDatesPicker
.dates
[type
][i
],
279 default: $.error('Format "'+format
+'" not supported!');
282 addDates : function( dates
, type
) {
283 if(dates
.length
> 0) {
284 if(!type
) type
= 'picked';
285 switch(typeof dates
) {
290 if (typeof dates
[i
] != "function")
291 addDate
.call(this, dates
[i
], type
, true);
292 sortDates
.call(this, type
);
294 } // else does the same as 'string'
297 addDate
.call(this, dates
, type
);
300 $.error('Date format "'+ typeof dates
+'" not allowed on jQuery.multiDatesPicker');
302 $(this).datepicker('refresh');
304 $.error('Empty array of dates received.');
307 removeDates : function( dates
, type
) {
308 if(!type
) type
= 'picked';
310 if (Object
.prototype.toString
.call(dates
) === '[object Array]') {
311 for(var i
in dates
.sort(function(a
,b
){return b
-a
})) {
312 removed
.push(removeDate
.call(this, dates
[i
], type
));
315 removed
.push(removeDate
.call(this, dates
, type
));
317 $(this).datepicker('refresh');
320 removeIndexes : function( indexes
, type
) {
321 if(!type
) type
= 'picked';
323 if (Object
.prototype.toString
.call(indexes
) === '[object Array]') {
324 for(var i
in indexes
.sort(function(a
,b
){return b
-a
})) {
325 removed
.push(removeIndex
.call(this, indexes
[i
], type
));
328 removed
.push(removeIndex
.call(this, indexes
, type
));
330 $(this).datepicker('refresh');
333 resetDates : function ( type
) {
334 if(!type
) type
= 'picked';
335 this.multiDatesPicker
.dates
[type
] = [];
336 $(this).datepicker('refresh');
338 toggleDate : function( date
, type
) {
339 if(!type
) type
= 'picked';
341 switch(this.multiDatesPicker
.mode
) {
343 this.multiDatesPicker
.dates
[type
] = []; // deletes all picked/disabled dates
344 var end
= this.multiDatesPicker
.autoselectRange
[1];
345 var begin
= this.multiDatesPicker
.autoselectRange
[0];
346 if(end
< begin
) { // switch
347 end
= this.multiDatesPicker
.autoselectRange
[0];
348 begin
= this.multiDatesPicker
.autoselectRange
[1];
350 for(var i
= begin
; i
< end
; i
++)
351 methods
.addDates
.call(this, methods
.sumDays(date
, i
), type
);
354 if(methods
.gotDate
.call(this, date
) === false) // adds dates
355 methods
.addDates
.call(this, date
, type
);
356 else // removes dates
357 methods
.removeDates
.call(this, date
, type
);
361 setMode : function( options
) {
363 if(options
.mode
) this.multiDatesPicker
.mode
= options
.mode
;
365 switch(this.multiDatesPicker
.mode
) {
367 for(option
in options
)
371 case 'pickableRange':
372 case 'adjustRangeToDisabled':
373 this.multiDatesPicker
[option
] = options
[option
];
375 //default: $.error('Option ' + option + ' ignored for mode "'.options.mode.'".');
381 for(option
in options
)
383 case 'autoselectRange':
385 case 'pickableRange':
386 case 'adjustRangeToDisabled':
387 this.multiDatesPicker
[option
] = options
[option
];
389 //default: $.error('Option ' + option + ' does not exist for setMode on jQuery.multiDatesPicker');
391 if(mandatory
> 0) $.error('Some mandatory options not specified!');
396 if(options.pickableRange) {
397 $this.datepicker("option", "maxDate", options.pickableRange);
398 $this.datepicker("option", "minDate", this.multiDatesPicker.minDate);
402 if(mdp_events
.onSelect
)
403 mdp_events
.onSelect();
404 $this.datepicker('refresh');
408 this.each(function() {
409 if (!this.multiDatesPicker
) {
410 this.multiDatesPicker
= {
416 adjustRangeToDisabled
: true
420 if(methods
[method
]) {
421 var exec_result
= methods
[method
].apply(this, Array
.prototype.slice
.call(mdp_arguments
, 1));
432 } else if( typeof method
=== 'object' || ! method
) {
433 return methods
.init
.apply(this, mdp_arguments
);
435 $.error('Method ' + method
+ ' does not exist on jQuery.multiDatesPicker');
440 if(method
!= 'gotDate' && method
!= 'getDates') {
447 var PROP_NAME
= 'multiDatesPicker';
448 var dpuuid
= new Date().getTime();
451 $.multiDatesPicker
= {version
: false};
452 //$.multiDatesPicker = new MultiDatesPicker(); // singleton instance
453 $.multiDatesPicker
.initialized
= false;
454 $.multiDatesPicker
.uuid
= new Date().getTime();
455 $.multiDatesPicker
.version
= $.ui
.multiDatesPicker
.version
;
457 // Workaround for #4055
458 // Add another global to avoid noConflict issues with inline event handlers
459 window
['DP_jQuery_' + dpuuid
] = $;